<template>
  <div class="dashboard-container">
    <div class="dashboard-header">
      <h2>仪表盘</h2>
      <div class="dashboard-actions">
        <el-tooltip content="刷新数据" placement="top">
          <el-button type="primary" :icon="Refresh" circle @click="refreshAllData" :loading="refreshing"></el-button>
        </el-tooltip>
        <el-tooltip content="自动刷新设置" placement="top">
          <el-dropdown trigger="click" @command="handleAutoRefreshChange">
            <el-button type="info" :icon="Timer" circle></el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item :command="0" :class="{ 'active-refresh': autoRefreshInterval === 0 }">关闭自动刷新</el-dropdown-item>
                <el-dropdown-item :command="30000" :class="{ 'active-refresh': autoRefreshInterval === 30000 }">每30秒</el-dropdown-item>
                <el-dropdown-item :command="60000" :class="{ 'active-refresh': autoRefreshInterval === 60000 }">每1分钟</el-dropdown-item>
                <el-dropdown-item :command="300000" :class="{ 'active-refresh': autoRefreshInterval === 300000 }">每5分钟</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </el-tooltip>
      </div>
    </div>
    
    <div class="dashboard-stats">
      <el-row :gutter="20">
        <el-col :span="6" v-for="(item, index) in statsData" :key="index">
          <el-card class="stat-card" :body-style="{ padding: '0px' }" shadow="hover">
            <div class="stat-card-inner" :style="{ backgroundColor: item.bgColor }">
              <div class="stat-icon" :style="{ backgroundColor: item.color }">
                <el-icon size="28">
                  <component :is="item.icon" />
                </el-icon>
              </div>
              <div class="stat-content">
                <div class="stat-value">{{ item.value }}</div>
                <div class="stat-label">{{ item.label }}</div>
              </div>
            </div>
          </el-card>
        </el-col>
      </el-row>
    </div>

    <div class="dashboard-charts">
      <el-row :gutter="20">
        <el-col :span="16">
          <el-card class="chart-card" shadow="hover">
              <div class="card-header">
                <h3>小区房产分布</h3>
              </div>
            <div class="chart-container">
              <div id="communityChart" style="width: 100%; height: 350px;"></div>
              <div v-if="loading.communityHomes" class="chart-loading">
                <el-icon class="is-loading"><Loading /></el-icon>
                <span>数据加载中...</span>
              </div>
            </div>
          </el-card>
        </el-col>
        <el-col :span="8">
          <el-card class="chart-card" shadow="hover">
              <div class="card-header">
                <h3>房产使用情况</h3>
              </div>
            <div class="chart-container">
              <div id="propertyChart" style="width: 100%; height: 350px;"></div>
              <div v-if="loading.homeUsage" class="chart-loading">
                <el-icon class="is-loading"><Loading /></el-icon>
                <span>数据加载中...</span>
              </div>
            </div>
          </el-card>
        </el-col>
      </el-row>
      
      <el-row :gutter="20" style="margin-top: 20px;">
        
        <el-col :span="12">
          <el-card class="chart-card" shadow="hover">
              <div class="card-header">
                <h3>人员分布统计</h3>
              </div>
            <div class="chart-container">
              <div id="personnelChart" style="width: 100%; height: 350px;"></div>
              <div v-if="loading.personnelDistribution" class="chart-loading">
                <el-icon class="is-loading"><Loading /></el-icon>
                <span>数据加载中...</span>
              </div>
            </div>
          </el-card>
        </el-col>
      </el-row>
    </div>

    <div class="dashboard-notices">
      <el-card class="notice-card" shadow="hover">
          <div class="card-header">
          <h3>系统通知</h3>
          </div>
        <div class="notice-list">
          <div 
            v-for="(notice, index) in noticeData" 
            :key="notice.id" 
            class="notice-item" 
            :class="notice.type"
          >
            <div class="notice-icon" :class="notice.type">
              <el-icon>
                <component :is="notice.icon" />
              </el-icon>
            </div>
            <div class="notice-content">
              <div class="notice-title">{{ notice.title }}</div>
              <div class="notice-desc">{{ notice.description }}</div>
          </div>
            <div class="notice-time">{{ notice.time }}</div>
          </div>
        </div>
      </el-card>
    </div>
  </div>
</template>

<script>
import * as echarts from 'echarts'
import { 
  House, 
  HomeFilled, 
  Van, 
  User, 
  Bell, 
  Tools, 
  Warning, 
  ChatDotRound,
  Promotion,
  Loading,
  Refresh,
  Timer
} from '@element-plus/icons-vue'
import axios from 'axios'

export default {
  name: 'Dashboard',
  components: {
    House,
    HomeFilled,
    Van,
    User,
    Bell,
    Tools,
    Warning,
    ChatDotRound,
    Promotion,
    Loading,
    Refresh,
    Timer
  },
  data() {
    return {
      statsData: [
        { label: '小区总数', value: 0, icon: 'House', color: '#409EFF', bgColor: 'rgba(64, 158, 255, 0.1)' },
        { label: '房产总数', value: 0, icon: 'HomeFilled', color: '#67C23A', bgColor: 'rgba(103, 194, 58, 0.1)' },
        { label: '停车位总数', value: 0, icon: 'Van', color: '#E6A23C', bgColor: 'rgba(230, 162, 60, 0.1)' },
        { label: '业主总数', value: 0, icon: 'User', color: '#F56C6C', bgColor: 'rgba(245, 108, 108, 0.1)' }
      ],
      noticeData: [
        { 
          id: 1,
        title: '系统维护通知', 
        description: '系统将于今晚22:00-23:00进行例行维护，请提前做好工作安排。', 
        time: '10分钟前',
        type: 'warning',
        icon: 'Bell'
      },
      { 
          id: 2,
        title: '新的维修请求', 
        description: '东湖小区3栋2单元501业主报修水管漏水问题，请及时处理。', 
        time: '30分钟前',
        type: 'info',
        icon: 'Tools'
      },
      { 
          id: 3,
        title: '投诉处理提醒', 
        description: '金华万府小区有3条投诉尚未处理，请相关人员尽快跟进。', 
        time: '1小时前',
        type: 'danger',
        icon: 'Warning'
      },
      { 
          id: 4,
        title: '业主信箱新消息', 
        description: '有5条新的业主留言需要回复，请及时查看处理。', 
        time: '2小时前',
        type: 'success',
        icon: 'ChatDotRound'
      },
      { 
          id: 5,
        title: '小区活动提醒', 
        description: '东湖小区将于本周六举办夏日纳凉晚会，请做好相关准备工作。', 
        time: '1天前',
        type: 'primary',
        icon: 'Promotion'
      }
      ],
      loading: {
        stats: false,
        communityHomes: false,
        homeUsage: false,
        parkingUsage: false,
        personnelDistribution: false
      },
      communityChart: null,
      propertyChart: null,
      parkingChart: null,
      personnelChart: null,
      autoRefreshInterval: 0,
      refreshing: false,
      isTokenRefreshing: false
    }
  },
  created() {
    // 添加请求拦截器，处理令牌过期情况
    this.setupAxiosInterceptors();
  },
  mounted() {
    this.fetchStats();
    this.initCommunityChart();
    this.initPropertyChart();
    this.initParkingChart();
    this.initPersonnelChart();

    // 添加窗口大小变化时重绘图表
    window.addEventListener('resize', this.handleResize);
    
    // 如果有设置自动刷新，启动自动刷新
    if (this.autoRefreshInterval > 0) {
      this.startAutoRefresh();
    }
  },
  beforeUnmount() {
    // 移除事件监听
    window.removeEventListener('resize', this.handleResize);
    
    // 停止自动刷新
    this.stopAutoRefresh();
    
    // 销毁图表实例
    if (this.communityChart) this.communityChart.dispose();
    if (this.propertyChart) this.propertyChart.dispose();
    if (this.parkingChart) this.parkingChart.dispose();
    if (this.personnelChart) this.personnelChart.dispose();
  },
  methods: {
    setupAxiosInterceptors() {
      // 添加响应拦截器
      axios.interceptors.response.use(
        response => {
          return response;
        },
        async error => {
          const originalRequest = error.config;
          
          // 检查是否有令牌过期的响应头
          if (error.response && error.response.headers['x-jwt-expired'] === 'true' && !originalRequest._retry) {
            // 防止多个请求同时尝试刷新令牌
            if (!this.isTokenRefreshing) {
              this.isTokenRefreshing = true;
              
              try {
                // 尝试刷新令牌
                const token = localStorage.getItem('token');
                if (token) {
                  const refreshResponse = await axios.post('/api/auth/refresh', {}, {
                    headers: {
                      'Authorization': `Bearer ${token}`
                    }
                  });
                  
                  if (refreshResponse.data && refreshResponse.data.token) {
                    // 更新存储的令牌
                    localStorage.setItem('token', refreshResponse.data.token);
                    
                    // 更新所有请求的令牌
                    axios.defaults.headers.common['Authorization'] = `Bearer ${refreshResponse.data.token}`;
                    
                    // 重试原始请求
                    originalRequest.headers['Authorization'] = `Bearer ${refreshResponse.data.token}`;
                    originalRequest._retry = true;
                    
                    this.$message.success('令牌已刷新');
                    this.isTokenRefreshing = false;
                    
                    return axios(originalRequest);
                  }
                }
                
                // 如果刷新失败，重定向到登录页面
                this.$message.error('会话已过期，请重新登录');
                setTimeout(() => {
                  localStorage.removeItem('token');
                  localStorage.removeItem('user');
                  this.$router.push('/login');
                }, 1500);
                
              } catch (refreshError) {
                console.error('令牌刷新失败:', refreshError);
                this.$message.error('会话已过期，请重新登录');
                setTimeout(() => {
                  localStorage.removeItem('token');
                  localStorage.removeItem('user');
                  this.$router.push('/login');
                }, 1500);
              } finally {
                this.isTokenRefreshing = false;
              }
            }
            
            // 如果已经在刷新令牌，则等待刷新完成后重试
            return new Promise(resolve => {
              const checkRefreshComplete = setInterval(() => {
                if (!this.isTokenRefreshing) {
                  clearInterval(checkRefreshComplete);
                  originalRequest.headers['Authorization'] = `Bearer ${localStorage.getItem('token')}`;
                  resolve(axios(originalRequest));
                }
              }, 100);
            });
          }
          
          // 对于其他错误，继续传递
          return Promise.reject(error);
        }
      );
    },
    
    handleResize() {
      if (this.communityChart) this.communityChart.resize();
      if (this.propertyChart) this.propertyChart.resize();
      if (this.parkingChart) this.parkingChart.resize();
      if (this.personnelChart) this.personnelChart.resize();
    },
    
    // 获取统计数据
    async fetchStats() {
      this.loading.stats = true;
      try {
        const response = await axios.get('/api/dashboard/stats');
        const data = response.data;
        
        // 更新统计卡片数据
        this.statsData[0].value = data.communityCount;
        this.statsData[1].value = data.homeCount;
        this.statsData[2].value = data.parkingCount;
        this.statsData[3].value = data.ownerCount;
      } catch (error) {
        console.error('获取统计数据失败:', error);
        this.$message.error('获取统计数据失败');
      } finally {
        this.loading.stats = false;
      }
    },
    
    // 初始化小区房产分布饼图
    async initCommunityChart() {
      this.loading.communityHomes = true;
      const chartDom = document.getElementById('communityChart');
      this.communityChart = echarts.init(chartDom);
      
      try {
        const response = await axios.get('/api/dashboard/community-homes');
        const data = response.data;
        
        // 为数据添加自定义颜色
        const colors = [
          '#409EFF', '#67C23A', '#E6A23C', '#F56C6C', '#909399',
          '#36CBCB', '#9C27B0', '#FF9800', '#795548', '#607D8B'
        ];
        
        data.forEach((item, index) => {
          item.itemStyle = {
            color: colors[index % colors.length]
          };
        });
      
        const option = {
          title: {
            text: '各小区房产数量分布',
            left: 'center',
            top: 0,
            textStyle: {
              color: '#303133',
              fontSize: 16,
              fontWeight: 'normal'
            }
          },
          tooltip: {
            trigger: 'item',
            formatter: '{a} <br/>{b}: {c} ({d}%)',
            backgroundColor: 'rgba(255, 255, 255, 0.9)',
            borderColor: '#eee',
            borderWidth: 1,
            textStyle: {
              color: '#333'
            },
            extraCssText: 'box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);'
          },
          legend: {
            orient: 'horizontal',
            bottom: 0,
            data: data.map(item => item.name),
            textStyle: {
              color: '#666'
            },
            icon: 'circle',
            itemWidth: 10,
            itemHeight: 10,
            itemGap: 20,
            type: 'scroll',
            pageButtonItemGap: 5,
            pageButtonGap: 5
          },
          series: [
            {
              name: '房产数量',
              type: 'pie',
              radius: ['30%', '65%'],
              center: ['50%', '45%'],
              data: data,
              roseType: 'radius',
              emphasis: {
                itemStyle: {
                  shadowBlur: 20,
                  shadowOffsetX: 0,
                  shadowColor: 'rgba(0, 0, 0, 0.5)'
                },
                label: {
                  show: true,
                  fontSize: 16,
                  fontWeight: 'bold'
                }
              },
              itemStyle: {
                borderRadius: 8,
                borderColor: '#fff',
                borderWidth: 2,
                shadowBlur: 10,
                shadowColor: 'rgba(0, 0, 0, 0.1)'
              },
                              label: {
                 show: false
                },
                labelLine: {
                 show: false
                },
              animationType: 'scale',
              animationEasing: 'elasticOut',
              animationDelay: function (idx) {
                return Math.random() * 300;
              }
            }
          ]
        };
        
        this.communityChart.setOption(option);
      } catch (error) {
        console.error('获取小区房产分布数据失败:', error);
        this.$message.error('获取小区房产分布数据失败');
      } finally {
        this.loading.communityHomes = false;
      }
    },

    // 初始化房产使用情况柱状图
    async initPropertyChart() {
      this.loading.homeUsage = true;
      const chartDom = document.getElementById('propertyChart');
      this.propertyChart = echarts.init(chartDom);
      
      try {
        const response = await axios.get('/api/dashboard/home-usage');
        const data = response.data;
        
        // 只显示前10个社区的数据
        const limitedData = {
          communities: data.communities.slice(0, 10),
          sold: data.sold.slice(0, 10),
          rented: data.rented.slice(0, 10),
          vacant: data.vacant.slice(0, 10)
        };
      
        const option = {
          tooltip: {
            trigger: 'axis',
            axisPointer: {
              type: 'shadow'
            },
            backgroundColor: 'rgba(255, 255, 255, 0.9)',
            borderColor: '#eee',
            borderWidth: 1,
            textStyle: {
              color: '#333'
            },
            extraCssText: 'box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);'
          },
          legend: {
            data: ['已售', '已租', '空置'],
            bottom: 0,
            textStyle: {
              color: '#666'
            },
            icon: 'rect'
          },
          grid: {
            left: '3%',
            right: '4%',
            bottom: '15%',
            top: '8%',
            containLabel: true
          },
          xAxis: {
            type: 'category',
            data: limitedData.communities,
            axisLabel: {
              interval: 0,
              rotate: 30,
              textStyle: {
                color: '#666'
              }
            }
          },
          yAxis: {
            type: 'value',
            splitLine: {
              lineStyle: {
                type: 'dashed',
                color: '#eee'
              }
            }
          },
          series: [
            {
              name: '已售',
              type: 'bar',
              stack: 'total',
              emphasis: {
                focus: 'series'
              },
              data: limitedData.sold.map(item => item.value),
              itemStyle: {
                borderRadius: [4, 4, 0, 0]
              },
              barWidth: '60%'
            },
            {
              name: '已租',
              type: 'bar',
              stack: 'total',
              emphasis: {
                focus: 'series'
              },
              data: limitedData.rented.map(item => item.value)
            },
            {
              name: '空置',
              type: 'bar',
              stack: 'total',
              emphasis: {
                focus: 'series'
              },
              data: limitedData.vacant.map(item => item.value)
            }
          ],
          color: ['#409EFF', '#67C23A', '#E6A23C']
        };
        
        this.propertyChart.setOption(option);
      } catch (error) {
        console.error('获取房产使用情况数据失败:', error);
        this.$message.error('获取房产使用情况数据失败');
      } finally {
        this.loading.homeUsage = false;
      }
    },

    // 初始化停车位使用情况环形图
    async initParkingChart() {
      this.loading.parkingUsage = true;
      const chartDom = document.getElementById('parkingChart');
      this.parkingChart = echarts.init(chartDom);
      
      try {
        const response = await axios.get('/api/dashboard/parking-usage');
        const data = response.data;
        
        // 确保数据存在且格式正确
        if (!data || !Array.isArray(data)) {
          console.error('停车位使用情况数据格式不正确:', data);
          this.$message.error('停车位使用情况数据格式不正确');
          return;
        }
      
        const option = {
          tooltip: {
            trigger: 'item',
            formatter: '{a} <br/>{b}: {c} ({d}%)',
            backgroundColor: 'rgba(255, 255, 255, 0.9)',
            borderColor: '#eee',
            borderWidth: 1,
            textStyle: {
              color: '#333'
            },
            extraCssText: 'box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);'
          },
          legend: {
            bottom: 0,
            left: 'center',
            data: data.map(item => item.name),
            textStyle: {
              color: '#666'
            },
            icon: 'circle',
            itemWidth: 10,
            itemHeight: 10,
            itemGap: 20
          },
          series: [
            {
              name: '停车位使用情况',
              type: 'pie',
              radius: ['40%', '70%'],
              center: ['50%', '40%'],
              avoidLabelOverlap: false,
              itemStyle: {
                borderRadius: 10,
                borderColor: '#fff',
                borderWidth: 2,
                shadowBlur: 10,
                shadowColor: 'rgba(0, 0, 0, 0.1)'
              },
              label: {
                show: true,
                position: 'outside',
                formatter: '{b}: {c} ({d}%)',
                color: '#666',
                fontSize: 14
              },
              emphasis: {
                label: {
                  show: true,
                  fontSize: 18,
                  fontWeight: 'bold',
                  color: '#333'
                },
                itemStyle: {
                  shadowBlur: 20,
                  shadowColor: 'rgba(0, 0, 0, 0.2)'
                }
              },
              labelLine: {
                show: true,
                length: 15,
                length2: 10,
                smooth: true
              },
              data: data,
              animationType: 'scale',
              animationEasing: 'elasticOut',
              animationDelay: function (idx) {
                return Math.random() * 200;
              }
            }
          ],
          color: ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C']
        };
        
        this.parkingChart.setOption(option);
      } catch (error) {
        console.error('获取停车位使用情况数据失败:', error);
        this.$message.error('获取停车位使用情况数据失败');
      } finally {
        this.loading.parkingUsage = false;
      }
    },
    

    
    // 初始化人员分布统计图
    async initPersonnelChart() {
      this.loading.personnelDistribution = true;
      const chartDom = document.getElementById('personnelChart');
      this.personnelChart = echarts.init(chartDom);
      
      try {
        const response = await axios.get('/api/dashboard/personnel-distribution');
        const data = response.data;
        
        // 只显示前10个社区的数据
        const limitedCommunities = data.communities.slice(0, 10);
        const limitedOwners = data.owners.slice(0, 10);
        const limitedFamilies = data.families.slice(0, 10);
        const limitedVisitors = data.visitors.slice(0, 10);
      
        const option = {
          tooltip: {
            trigger: 'axis',
            axisPointer: {
              type: 'shadow'
            },
            backgroundColor: 'rgba(255, 255, 255, 0.9)',
            borderColor: '#eee',
            borderWidth: 1,
            textStyle: {
              color: '#333'
            },
            extraCssText: 'box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);'
          },
          legend: {
            data: ['业主', '家庭成员', '访客'],
            bottom: 0,
            textStyle: {
              color: '#666'
            },
            icon: 'rect'
          },
          grid: {
            left: '3%',
            right: '4%',
            bottom: '15%',
            top: '8%',
            containLabel: true
          },
          xAxis: {
            type: 'value',
            boundaryGap: [0, 0.01],
            splitLine: {
              lineStyle: {
                type: 'dashed',
                color: '#eee'
              }
            }
          },
          yAxis: {
            type: 'category',
            data: limitedCommunities,
            axisLabel: {
              color: '#666'
            }
          },
          series: [
            {
              name: '业主',
              type: 'bar',
              data: limitedOwners,
              itemStyle: {
                borderRadius: [0, 4, 4, 0]
              },
              barWidth: '15',
              barGap: '10%'
            },
            {
              name: '家庭成员',
              type: 'bar',
              data: limitedFamilies,
              itemStyle: {
                borderRadius: [0, 4, 4, 0]
              },
              barWidth: '15'
            },
            {
              name: '访客',
              type: 'bar',
              data: limitedVisitors,
              itemStyle: {
                borderRadius: [0, 4, 4, 0]
              },
              barWidth: '15'
            }
          ],
          color: ['#409EFF', '#67C23A', '#E6A23C']
        };
        
        this.personnelChart.setOption(option);
      } catch (error) {
        console.error('获取人员分布统计数据失败:', error);
        this.$message.error('获取人员分布统计数据失败');
      } finally {
        this.loading.personnelDistribution = false;
      }
    },
    async refreshAllData() {
      this.refreshing = true;
      try {
        await this.fetchStats();
        await this.initCommunityChart();
        await this.initPropertyChart();
        await this.initParkingChart();
        await this.initPersonnelChart();
        this.$message.success('数据刷新成功');
      } catch (error) {
        console.error('刷新数据失败:', error);
        this.$message.error('刷新数据失败');
      } finally {
        this.refreshing = false;
      }
    },
    handleAutoRefreshChange(command) {
      this.autoRefreshInterval = command;
      if (this.autoRefreshInterval > 0) {
        this.startAutoRefresh();
      } else {
        this.stopAutoRefresh();
      }
    },
    startAutoRefresh() {
      if (this.autoRefreshInterval > 0) {
        this.refreshInterval = setInterval(this.refreshAllData, this.autoRefreshInterval);
      }
    },
    stopAutoRefresh() {
      clearInterval(this.refreshInterval);
    }
  }
}
</script>

<style scoped>
@keyframes fadeInRight {
  from {
    opacity: 0;
    transform: translateX(20px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(64, 158, 255, 0.4);
  }
  70% {
    box-shadow: 0 0 0 10px rgba(64, 158, 255, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(64, 158, 255, 0);
  }
}

.dashboard-container {
  padding: 20px;
}

.dashboard-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.dashboard-header h2 {
  margin: 0;
  font-size: 24px;
  font-weight: 600;
  color: #303133;
}

.dashboard-actions {
  display: flex;
  align-items: center;
}

.dashboard-stats {
  margin-bottom: 20px;
}

.stat-card {
  padding: 15px;
  height: 120px;
  margin-bottom: 20px;
  transition: all 0.3s;
  overflow: hidden;
  position: relative;
  border: none;
  border-radius: 15px;
  background: linear-gradient(135deg, #ffffff 0%, #f5f7fa 100%);
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.08);
}

.stat-card:hover {
  transform: translateY(-8px);
  box-shadow: 0 15px 30px rgba(0, 0, 0, 0.15);
}

.stat-card:before {
  content: '';
  position: absolute;
  top: -30px;
  right: -30px;
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.15);
  opacity: 0.8;
}

.stat-card:after {
  content: '';
  position: absolute;
  bottom: -20px;
  left: -20px;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.03);
  opacity: 0.8;
}

.stat-card-inner {
  display: flex;
  align-items: center;
  height: 100%;
  position: relative;
  z-index: 1;
}

.stat-icon {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 85px;
  height: 85px;
  border-radius: 18px;
  margin-right: 20px;
  flex-shrink: 0;
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15);
  background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0) 100%);
  animation: pulse 2s infinite;
}

.stat-icon .el-icon {
  font-size: 42px;
  color: white;
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.3));
}

.stat-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.stat-value {
  font-size: 36px;
  font-weight: bold;
  margin-bottom: 8px;
  color: #303133;
  text-shadow: 0 2px 3px rgba(0, 0, 0, 0.1);
  animation: fadeInRight 0.8s ease-out forwards;
}

.stat-label {
  font-size: 18px;
  color: #606266;
  font-weight: 500;
  position: relative;
  padding-bottom: 5px;
}

.stat-label:after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 30px;
  height: 3px;
  background: #409EFF;
  border-radius: 3px;
  opacity: 0.7;
}

.dashboard-charts {
  margin-bottom: 20px;
}

.chart-card {
  margin-bottom: 20px;
  height: 450px;
  transition: all 0.3s;
  border: none;
  border-radius: 15px;
  background: linear-gradient(135deg, #ffffff 0%, #f5f7fa 100%);
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.08);
  position: relative;
  overflow: hidden;
}

.chart-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 15px 30px rgba(0, 0, 0, 0.15);
}

.chart-card:before {
  content: '';
  position: absolute;
  top: -30px;
  right: -30px;
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.15);
  opacity: 0.8;
  z-index: 0;
}

.chart-container {
  position: relative;
  height: 300px;
  width: 100%;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15px 20px;
  border-bottom: 1px solid rgba(240, 240, 240, 0.8);
  position: relative;
  z-index: 1;
}

.card-header h3 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: #303133;
  position: relative;
  padding-left: 15px;
}

.card-header h3:before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 20px;
  background: #409EFF;
  border-radius: 2px;
  box-shadow: 0 2px 5px rgba(64, 158, 255, 0.3);
}

.dashboard-notices {
  position: relative;
}

.dashboard-notices:before {
  content: '';
  position: absolute;
  top: 20px;
  right: 20px;
  width: 80px;
  height: 80px;
  background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23409EFF" opacity="0.1"><path d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6-6v-5c0-3.07-1.63-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.64 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2zm-2 1H8v-6c0-2.48 1.51-4.5 4-4.5s4 2.02 4 4.5v6z"></path></svg>') no-repeat center center;
  background-size: contain;
  opacity: 0.15;
  z-index: 1;
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.1));
  animation: pulse 3s infinite;
}

.notice-card {
  margin-bottom: 20px;
  border: none;
  border-radius: 15px;
  background: linear-gradient(135deg, #ffffff 0%, #f5f7fa 100%);
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.08);
  transition: all 0.3s;
  position: relative;
  overflow: hidden;
}

.notice-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 15px 30px rgba(0, 0, 0, 0.15);
}

.notice-card:before {
  content: '';
  position: absolute;
  bottom: -30px;
  left: -30px;
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.02);
  opacity: 0.8;
  z-index: 0;
}

.notice-card .card-header {
  border-bottom: 1px solid rgba(240, 240, 240, 0.8);
}

.notice-card .card-header h3 {
  font-size: 20px;
  font-weight: 600;
  color: #303133;
  position: relative;
  padding-left: 15px;
  display: flex;
  align-items: center;
}

.notice-card .card-header h3:before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 22px;
  background: #409EFF;
  border-radius: 2px;
  box-shadow: 0 2px 5px rgba(64, 158, 255, 0.3);
}

.notice-list {
  max-height: 400px;
  overflow-y: auto;
  padding: 15px 15px;
  position: relative;
  z-index: 1;
  scrollbar-width: thin;
  scrollbar-color: #dcdfe6 #f2f6fc;
}

.notice-list::-webkit-scrollbar {
  width: 6px;
}

.notice-list::-webkit-scrollbar-thumb {
  background-color: #dcdfe6;
  border-radius: 3px;
}

.notice-list::-webkit-scrollbar-track {
  background-color: #f2f6fc;
}

.notice-item {
  display: flex;
  align-items: flex-start;
  padding: 20px 15px;
  margin-bottom: 10px;
  border-bottom: 1px solid #ebeef5;
  transition: all 0.3s;
  border-radius: 8px;
  position: relative;
  animation: fadeInRight 0.5s ease-out forwards;
  animation-delay: calc(0.1s * var(--index, 0));
  opacity: 0;
}

.notice-item:nth-child(1) {
  --index: 1;
}

.notice-item:nth-child(2) {
  --index: 2;
}

.notice-item:nth-child(3) {
  --index: 3;
}

.notice-item:nth-child(4) {
  --index: 4;
}

.notice-item:nth-child(5) {
  --index: 5;
}

.notice-item:hover {
  background-color: #f9fafc;
  transform: translateX(5px);
}

.notice-item:last-child {
  border-bottom: none;
  margin-bottom: 0;
}

.notice-item:before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 70%;
  border-radius: 2px;
  opacity: 0.8;
}

.notice-item.warning:before {
  background-color: #E6A23C;
}

.notice-item.info:before {
  background-color: #909399;
}

.notice-item.danger:before {
  background-color: #F56C6C;
}

.notice-item.success:before {
  background-color: #67C23A;
}

.notice-item.primary:before {
  background-color: #409EFF;
}

.notice-icon {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  margin-right: 20px;
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1);
  flex-shrink: 0;
}

.notice-icon .el-icon {
  font-size: 28px;
  color: white;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.2));
}

.notice-icon.warning {
  background: linear-gradient(135deg, #E6A23C 0%, #F3D19E 100%);
}

.notice-icon.info {
  background: linear-gradient(135deg, #909399 0%, #C8C9CC 100%);
}

.notice-icon.danger {
  background: linear-gradient(135deg, #F56C6C 0%, #FAB6B6 100%);
  animation: pulse 2s infinite;
}

.notice-icon.success {
  background: linear-gradient(135deg, #67C23A 0%, #B3E19D 100%);
}

.notice-icon.primary {
  background: linear-gradient(135deg, #409EFF 0%, #A0CFFF 100%);
}

.notice-content {
  flex: 1;
  padding-top: 5px;
}

.notice-title {
  font-size: 18px;
  font-weight: bold;
  margin-bottom: 10px;
  color: #303133;
}

.notice-desc {
  font-size: 16px;
  color: #606266;
  line-height: 1.6;
}

.notice-time {
  font-size: 14px;
  color: #909399;
  min-width: 90px;
  text-align: right;
  font-weight: 500;
  padding-top: 5px;
}

@media (max-width: 768px) {
  .stat-card {
    margin-bottom: 15px;
  }
  
  .chart-card {
    height: auto;
  }
  
  .chart-container {
    height: 250px;
  }
}

.chart-loading {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(255, 255, 255, 0.7);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  z-index: 10;
}

.chart-loading .el-icon {
  font-size: 24px;
  color: #409EFF;
  margin-bottom: 10px;
}

.active-refresh {
  background-color: #ecf5ff;
  color: #409EFF;
}
</style>
